/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package algorithms;

import genotypes.Angles;
import genotypes.AnglesPopulation;
import genotypes.UnacceptableAnglesComparator;
import java.util.Arrays;
import objectives.ObjectiveFunction;
import operators.CrossoverOperator;
import operators.MutationOperator;
import operators.SelectionOperator;
import operators.SplitOperator;

/**
 *
 * @author Gość
 */
public class IDEADynamic {

    private IDEAStepByStep subevolutionIDEA;
    private int subEvolveIters = 20;
    private SplitOperator sOp;
    private int unacceptableSize;
    private int popSize;
    private int anglesLength;
    private SelectionOperator rOp;

    public IDEADynamic(CrossoverOperator cOp, MutationOperator mOp, SplitOperator sOp,
            SelectionOperator rOp, ObjectiveFunction f, int popSize, int anglesLength,
            int unacceptableSize, double[][] limitations) {
        subevolutionIDEA = new IDEAStepByStep(cOp, mOp, sOp, rOp, f, popSize, anglesLength,
                unacceptableSize, limitations);
        this.sOp = sOp;
        this.rOp = rOp;
        this.unacceptableSize = unacceptableSize;
        this.popSize = popSize;
        this.anglesLength = anglesLength;
        
    }

    private Boolean changedFlag;
    private ObjectiveFunction sharedF;
    public void injectSharedObjectiveFunctionAndChangedFlag(ObjectiveFunction sharedF,
            Boolean changedFlag) {
        this.changedFlag = changedFlag;
        this.sharedF = sharedF;
        
    }
    public void nextStep() throws Exception {
        //sprawdz czy sie zminilo
       
        

        if (changedFlag) {
            subevolutionIDEA.setChangedObjectiveFunction(sharedF);
            subevolutionIDEA.getRecentPopulation().evaluate(sharedF);
            changedFlag = Boolean.FALSE;
        }


        subevolutionIDEA.retainAcceptablePopulation();

        for (int i = 0; i < subEvolveIters; i++) {
            System.out.println("subevolution step: "+i);
            subevolutionIDEA.nextStep();
        }
        AnglesPopulation c = subevolutionIDEA.getRecentPopulation();
        c.evaluate(sharedF);
        AnglesPopulation splitted[] = sOp.split(subevolutionIDEA.getRecentPopulation(),
                c);
        AnglesPopulation unaccPop = splitted[1];
        AnglesPopulation accPop = splitted[0];
       
        
        accPop = rOp.select(accPop);
        unaccPop = rOp.select(unaccPop);

        Angles unacceptables[] = unaccPop.getPopulation();
        Arrays.sort(unacceptables, new UnacceptableAnglesComparator());

        int unaccBest = unaccPop.getSize();
        if (unaccBest > unacceptableSize) {
            unaccBest = unacceptableSize;
        }

        Angles bestUnacc[] = new Angles[unaccBest];

        for (int i = 0; i < unaccBest; i++) {
            bestUnacc[i] = unacceptables[i];
        }

        int accBest = popSize - unaccBest;
        subevolutionIDEA.injectPopulation(
                AnglesPopulation.merge(accPop.bestIndividuals(accBest), bestUnacc));
        
    }

    public AnglesPopulation getRecentPopulation() {
        return subevolutionIDEA.getRecentPopulation();
    }

    public Angles getBestSoFar() {
        return subevolutionIDEA.getBestSoFar();
    }
}
